package com.gitee.xzb617.mybatis.sqllog.util;

import com.gitee.xzb617.mybatis.sqllog.SqlLogPlugin;
import org.springframework.util.AntPathMatcher;

import java.util.List;

/**
 * 调用栈工具类
 * @author xuzhibin
 */
public class StackTraceUtil {

    private final static String SQLLOG_CLASS_NAME = SqlLogPlugin.class.getSimpleName();

    /**
     * 是否匹配到是内部方法执行sql
     * @param stackTrace
     * @param packageMatchRules
     * @return
     */
    public static boolean isInnerFunction(StackTraceElement[] stackTrace, List<String> packageMatchRules) {
        boolean result = false;
        for (StackTraceElement stackTraceElement : stackTrace) {
            String className = stackTraceElement.getClassName();
            if (matchRegex(className, packageMatchRules)) {
                result = true;
                break;
            }
        }
        return result;
    }


    /**
     * 过滤有效的堆栈信息
     * @param stackTrace
     * @param packageMatchRules
     * @return
     */
    public static String filterEffectiveStackTraceElement(StackTraceElement[] stackTrace, List<String> packageMatchRules) {
        StringBuilder builder = new StringBuilder();
        for (StackTraceElement stackTraceElement : stackTrace) {
            String className = stackTraceElement.getClassName();
            boolean containPackagePrefix = matchRegex(className, packageMatchRules);
            if (containPackagePrefix && !className.contains("$$")
                    && !className.contains(SQLLOG_CLASS_NAME)) {
                builder.append("\n\t").append(stackTraceElement);
            }
        }
        String res = builder.toString();
        if ("".equals(res)) {
            return "[=== 无 ===]";
        }
        return res.trim();
    }


    /**
     * 有效的包路径前缀
     * @param className
     * @param basePackagePrefix
     * @return
     */
    private static boolean containPackagePrefix(String className, List<String> basePackagePrefix) {
        boolean result = false;
        for (String packagePrefix : basePackagePrefix) {
            if (className.contains(packagePrefix)) {
                result = true;
                break;
            }
        }
        return result;
    }

    private final static AntPathMatcher matcher = new AntPathMatcher();

    private static boolean matchRegex(String className, List<String> matchRules) {
        boolean result = false;
        for (String rule : matchRules) {
            if (matcher.match(rule, className)) {
                result = true;
                break;
            }
        }
        return result;
    }

}
